package com.yzkj.siot.facade.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yzkj.siot.context.CurUserCtx;
import com.yzkj.siot.domain.AdminAdmin;
import com.yzkj.siot.domain.AdminTenant;
import com.yzkj.siot.domain.TenantUser;
import com.yzkj.siot.exp.BizExp;
import com.yzkj.siot.facade.AuthFacade;
import com.yzkj.siot.facade.TenantFacade;
import com.yzkj.siot.req.TenantRegisterReq;
import com.yzkj.siot.req.TenantRegisterVerifyCodeReq;
import com.yzkj.siot.service.AdminAdminService;
import com.yzkj.siot.service.AdminTenantService;
import com.yzkj.siot.service.TenantUserService;
import com.yzkj.siot.token.TokenHelper;
import com.yzkj.siot.util.EmailHelper;
import com.yzkj.siot.util.RedisUtil;
import com.yzkj.siot.vo.LoginResponse;

import cn.hutool.captcha.generator.RandomGenerator;
import cn.hutool.core.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;

import javax.mail.MessagingException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

@Slf4j
@Service
public class TenantAuthFacadeImpl implements AuthFacade {

	@Autowired
	TenantUserService tenantUserService;

	@Autowired
	AdminTenantService adminTenantService;

	@Autowired
	AdminAdminService adminAdminService;

	@Autowired
	EmailHelper emailHelper;

	@Autowired
	TemplateEngine templateEngine;

	@Autowired
	TenantFacade tenantFacade;

	@Autowired
	RedisUtil redisUtil;

	@Value("${redisKey.tenant-create-verify-code}")
	String tenantCreateVerifyCodeRedisKey;

	@Value("${sys.tenant.createVerifyCodeExpire}")
	Integer createVerifyCodeExpire;

	@Override
	public LoginResponse tenantLogin(String userName, String password, String tenantAlias) {

		// get tenant form tenantAlias
		QueryWrapper<AdminTenant> tenantQueryWrapper = new QueryWrapper<>();
		tenantQueryWrapper.lambda().eq(AdminTenant::getTenantAlias, tenantAlias);

		AdminTenant tenant = adminTenantService.getOne(tenantQueryWrapper, false);

		if (tenant == null) {
			throw new BizExp("租户不存在");
		}

		if (tenant.getStatus() == 2) {
			throw new BizExp("租户未启用");
		}

		// get user
		QueryWrapper<TenantUser> userQueryWrapper = new QueryWrapper<>();
		userQueryWrapper.lambda().eq(TenantUser::getUserName, userName).eq(TenantUser::getTenantId, tenant.getId());

		TenantUser user = tenantUserService.getOne(userQueryWrapper, false);

		if (user == null) {
			throw new BizExp("不存在的用户名");
		}

		if (!user.getPassword().equals(password)) {
			throw new BizExp("用户名或密码错误");
		}

		String token = TokenHelper.create(user.getId(), user.getTenantId(), user.getRoleId(), 2, user.getUserEmail());

		return new LoginResponse("tenant", user.getUserName(), tenant.getId(), tenant.getTenantName(),
				user.getUserEmail(), token);
	}

	@Override
	public LoginResponse adminLogin(String nickName, String password) {

		// 获取此用户名的用户
		QueryWrapper<AdminAdmin> adminQueryWrapper = new QueryWrapper<>();
		adminQueryWrapper.lambda().eq(AdminAdmin::getNickName, nickName);

		AdminAdmin admin = adminAdminService.getOne(adminQueryWrapper, false);

		if (admin == null) {
			throw new BizExp("不存在的用户名");
		}

		if (!admin.getPassword().equals(password)) {
			throw new BizExp("用户名或密码错误");
		}

		String token = TokenHelper.create(admin.getId(), 0, 0, 1, null);

		return new LoginResponse("admin", admin.getNickName(), 0, null, null, token);
	}

	@Override
	public Boolean tenantUpdatePwd(String oldPwd, String newPwd) {

		Integer curUserId = CurUserCtx.get().getUserId();

		TenantUser tenantUser = tenantUserService.getById(curUserId);

		if (tenantUser == null) {
			throw new BizExp("用户不存在");
		}

		if (!tenantUser.getPassword().equals(oldPwd)) {
			throw new BizExp("密码错误");
		}

		tenantUser.setPassword(newPwd);

		return tenantUserService.updateById(tenantUser);
	}

	@Override
	public LoginResponse getGatewayToken(String tenantAlias, String tenantPwd) {

		QueryWrapper<AdminTenant> where = new QueryWrapper<>();
		where.lambda().eq(AdminTenant::getTenantAlias, tenantAlias);

		AdminTenant tenant = adminTenantService.getOne(where, false);

		if (tenant == null) {
			throw new BizExp("租户不存在");
		}

		if (!tenant.getTenantPwd().equals(tenantPwd)) {
			throw new BizExp("租户密码错误");
		}

		String token = TokenHelper.create(0, tenant.getId(), 0, 3, null);
		return new LoginResponse("tenant_gateway", null, tenant.getId(), null, tenant.getTenantName(), token);
	}

	@Override
	public Boolean tenantRegisterCreateVerifyCode(TenantRegisterVerifyCodeReq tenantRegisterVerifyCodeReq) {

		try {

			// 创建验证码
			String verifyCode = new RandomGenerator(4).generate();

			// 验证码存储到redis 有效期5分钟
			redisUtil.set(tenantCreateVerifyCodeRedisKey + tenantRegisterVerifyCodeReq.getUserEmail(), verifyCode,
					createVerifyCodeExpire);

			// 创建一个HTML模板主体
			Context context = new Context();
			// 设置项目变量
			context.setVariable("verifyCode", verifyCode);
			context.setVariable("exp", createVerifyCodeExpire / 60);
			// 模板引擎指向welcome.html页面
			String emailTemplate = templateEngine.process("TenantRegisterVerifyCodeTemplate", context);

			emailHelper.sendHtmlEmail("【SIOT】租户开通邮箱验证", emailTemplate, tenantRegisterVerifyCodeReq.getUserEmail());
			return Boolean.TRUE;
		} catch (MessagingException e) {
			log.error("发送租户开通验证码失败", e);
			return Boolean.FALSE;
		}
	}

	@Override
	public AdminTenant tenantRegister(TenantRegisterReq tenantRegisterReq) {

		// 校验验证码
		Object verifyCodeObj = redisUtil.get(tenantCreateVerifyCodeRedisKey + tenantRegisterReq.getUserEmail());
		if (verifyCodeObj == null) {
			throw new BizExp("验证码不存在或已过期");
		}

		if (!verifyCodeObj.toString().equals(tenantRegisterReq.getVerifyCode())) {
			throw new BizExp("验证码错误");
		}

		AdminTenant create = new AdminTenant();
		BeanUtil.copyProperties(tenantRegisterReq, create);
		create.setUserEmail(tenantRegisterReq.getUserEmail());

		return tenantFacade.saveOrUpdate(create);
	}

}
